<script setup>
import { ref } from 'vue'
import { useVueFlow, VueFlow } from '@vue-flow/core'
import { Controls } from '@vue-flow/controls'
import '@vue-flow/controls/dist/style.css'
import SpecialNode from '@/components/flow/SpecialNode.vue'
import SpecialEdge from '@/components/flow/SpecialEdge.vue'
import { useLayout } from './useLayout'
import dayjs from 'dayjs'
import { useRoute, useRouter } from 'vue-router'
import { approvalTemplateDetail, approvalTemplateEdit } from '@/api/approval/index.js'
import { ElMessage } from 'element-plus'
import { ArrowLeftBold } from '@element-plus/icons-vue'
import ShenpiForm from '@/views/menu/approval/component/ShenpiForm.vue'
import TiaojianForm from '@/views/menu/approval/component/TiaojianForm.vue'
import BanliForm from '@/views/menu/approval/component/BanliForm.vue'
import ChaosongForm from '@/views/menu/approval/component/ChaosongForm.vue'
import { listUser } from '@/api/system/user.js'

const route = useRoute()
const router = useRouter()

const nodes = ref([
  {
    id: 'a',
    position: { x: 500, y: 50 },
    data: { nodeTitle: '提交', deletable: false, value: [] },
    type: 'custom',
    draggable: true,
  },
  {
    id: 'b',
    position: { x: 500, y: 300 },
    data: {
      nodeTitle: '审批',
      deletable: true,
      value: [],
    },
    type: 'custom',
    draggable: true,
  },
  {
    id: 'c',
    position: { x: 500, y: 450 },
    data: { nodeTitle: '结束', deletable: false, value: [] },
    type: 'custom',
    draggable: true,
  },
])

const edges = ref([
  {
    id: 'a-b',
    source: 'a',
    target: 'b',
    sourceHandle: 'source-b',
    targetHandle: 'target-t',
    sourcePosition: 'bottom',
    targetPosition: 'top',
    type: 'custom',
  },
  {
    id: 'b-c',
    source: 'b',
    target: 'c',
    sourceHandle: 'source-b',
    targetHandle: 'target-t',
    sourcePosition: 'bottom',
    targetPosition: 'top',
    type: 'custom',
  },
])

const { layout } = useLayout()

const { fitView, toObject, fromObject } = useVueFlow()


const userList = ref([])
onMounted(async () => {
  const { approve } = (await approvalTemplateDetail(route.query.ruleId)).data
  if (approve) {
    await fromObject(JSON.parse(approve))
  }

  userList.value = (await listUser({ pageNum: 1, pageSize: 9999 })).rows
})

const { addNodes, addEdges } = useVueFlow()

async function layoutGraph() {
  await nextTick(() => {
    nodes.value = layout(nodes.value, edges.value, 'TB')
  })
  await fitView()
}

function generateNode(direction, source, target, nodeType) {
  let x = 0
  let y = 0
  let sourceHandle = ''
  let targetHandle = ''
  let sourcePosition = ''
  let targetPosition = ''
  const sourceNode = nodes.value.find((node) => node.id === source)
  let targetNode = nodes.value.find((node) => node.id === target)
  if (!targetNode) {
    targetNode = nodes.value.find((node) => node.id === 'c')
  }
  switch (direction) {
    case 'left':
      x = (sourceNode.position.x + targetNode.position.x) / 2
      y = (sourceNode.position.y + targetNode.position.y) / 2
      sourceHandle = 'source-l'
      targetHandle = 'target-r'
      sourcePosition = 'left'
      targetPosition = 'right'
      break
    case 'right':
      x = (sourceNode.position.x + targetNode.position.x) / 2
      y = (sourceNode.position.y + targetNode.position.y) / 2
      sourceHandle = 'source-r'
      targetHandle = 'target-l'
      sourcePosition = 'right'
      targetPosition = 'left'
      break
    case 'top':
      x = (sourceNode.position.x + targetNode.position.x) / 2
      y = (sourceNode.position.y + targetNode.position.y) / 2
      sourceHandle = 'source-t'
      targetHandle = 'target-b'
      sourcePosition = 'top'
      targetPosition = 'bottom'
      break
    case 'bottom':
      x = (sourceNode.position?.x + targetNode.position?.x) / 2
      y = (sourceNode.position?.y + targetNode.position?.y) / 2
      sourceHandle = 'source-b'
      targetHandle = 'target-t'
      sourcePosition = 'bottom'
      targetPosition = 'top'
      break
  }
  return {
    id: dayjs().valueOf().toString(),
    position: {
      x: x,
      y: y + 50,
    },
    data: {
      nodeTitle: nodeType,
      deletable: true,
      value: [],
    },
    type: 'custom',
    draggable: true,
    sourceHandle: sourceHandle,
    targetHandle: targetHandle,
    sourcePosition: sourcePosition,
    targetPosition: targetPosition,
  }
}

function onAddNode(param) {
  // add a single node to the graph
  let { direction, source, target, nodeType } = param
  const newNode = generateNode(direction, source, target, nodeType)

  addNodes(newNode)
  if (!target) {
    target = 'c'
  }
  addEdges([
    {
      id: `${source}-${newNode.id}`,
      source: source,
      target: newNode.id,
      sourceHandle: newNode.sourceHandle,
      targetHandle: newNode.targetHandle,
      sourcePosition: newNode.sourceHandle,
      targetPosition: newNode.targetHandle,
      type: 'custom',
    },
    {
      id: `${newNode.id}-${target}`,
      source: newNode.id,
      target: target,
      sourceHandle: newNode.sourceHandle,
      targetHandle: newNode.targetHandle,
      sourcePosition: newNode.sourceHandle,
      targetPosition: newNode.targetHandle,
      type: 'custom',
    },
  ])

}

const drawer = ref(false)
const currentNode = ref({
  data: {
    nodeTitle: '',
    value: [],
  },
})
const handleNodeClick = (param) => {
  currentNode.value = param.node
  drawer.value = true
  console.log('currentNode', currentNode.value)
}

const newFlow = () => {
  nodes.value = [
    {
      id: 'a',
      position: { x: 500, y: 50 },
      data: { nodeTitle: '提交', deletable: false, value: [] },
      type: 'custom',
      draggable: true,
    },
    {
      id: 'b',
      position: { x: 500, y: 300 },
      data: {
        nodeTitle: '审批',
        deletable: true,
        value: [],
      },
      type: 'custom',
      draggable: true,
    },
    {
      id: 'c',
      position: { x: 500, y: 450 },
      data: { nodeTitle: '结束', deletable: false, value: [] },
      type: 'custom',
      draggable: true,
    },
  ]
  edges.value = [
    {
      id: 'a-b',
      source: 'a',
      target: 'b',
      sourceHandle: 'source-b',
      targetHandle: 'target-t',
      sourcePosition: 'bottom',
      targetPosition: 'top',
      type: 'custom',
    },
    {
      id: 'b-c',
      source: 'b',
      target: 'c',
      sourceHandle: 'source-b',
      targetHandle: 'target-t',
      sourcePosition: 'bottom',
      targetPosition: 'top',
      type: 'custom',
    },
  ]
}

function updateNodesWithChildren() {
  nodes.value.forEach((node) => {
    const children = edges.value
      .filter((edge) => edge.source === node.id)
      .map((edge) => edge.target)

    node.data.children = children
  })
}

const saveFlow = () => {
  updateNodesWithChildren()
  const temp = toObject()
  approvalTemplateEdit({
    approve: JSON.stringify(temp),
    ruleId: route.query.ruleId,
  })
    .then(() => {
      ElMessage({
        message: '保存成功',
        type: 'success',
      })
      setTimeout(() => {
        window.location.reload()
      }, 1000)
    })
    .catch(() => {
      ElMessage({
        message: '保存失败',
        type: 'error',
      })
    })
}

const handleCancle = () => {
  drawer.value = false
}

const handleConfirm = (data) => {
  nodes.value = nodes.value.map((node) => {
    if (node.id === currentNode.value.id) {
      node.data.value = data
    }
    return node
  })
  drawer.value = false
  console.log('nodes', nodes.value)
}
</script>
<template>
  <div style="display: flex; justify-content: space-between; margin-top: 20px">
    <div class="title">
      <el-icon @click="router.go(-1)">
        <ArrowLeftBold />
      </el-icon>
      审批流程管理-{{ route.query.title }}
    </div>
    <div class="button-group">
      <el-button @click="newFlow">新建</el-button>
      <el-button plain type="success" @click="layoutGraph">自动整理</el-button>
      <el-button type="primary" @click="saveFlow">发布</el-button>
    </div>
  </div>
  <div class="layout-flow">
    <VueFlow v-model:edges="edges" v-model:nodes="nodes" @node-click="handleNodeClick">
      <template #node-custom="props">
        <SpecialNode v-bind="props" :userList="userList" />
      </template>
      <template #edge-custom="specialEdgeProps">
        <SpecialEdge v-bind="specialEdgeProps" @addNode="onAddNode" />
      </template>
      <Controls :show-interactive="false" />
    </VueFlow>

    <el-drawer v-model="drawer" direction="rtl" size="40%" destroy-on-close>
      <template #header>
        <div class="drawer-title">{{ currentNode.data.nodeTitle }}</div>
      </template>
      <template #default>
        <!--    审批-->
        <ShenpiForm
          v-if="currentNode.data.nodeTitle === '审批'"
          :value="currentNode.data.value"
          @cancleClick="handleCancle"
          @confirmClick="handleConfirm"
        />
        <!--    办理-->
        <BanliForm
          v-if="currentNode.data.nodeTitle === '办理'"
          :value="currentNode.data.value"
          @cancleClick="handleCancle"
          @confirmClick="handleConfirm"
        />
        <!--    抄送-->
        <ChaosongForm
          v-if="currentNode.data.nodeTitle === '抄送'"
          :value="currentNode.data.value"
          @cancleClick="handleCancle"
          @confirmClick="handleConfirm"
        />
        <!--    条件分支-->
        <TiaojianForm
          v-if="currentNode.data.nodeTitle === '条件分支'"
          :value="currentNode.data.value"
          @cancleClick="handleCancle"
          @confirmClick="handleConfirm"
        />
      </template>
    </el-drawer>
  </div>
</template>

<style lang="scss" scoped>
.title {
  margin-left: 20px;
  color: #303133;
  font-feature-settings:
    'ss01' on,
    'ss04' on;
  font-family: 'MiSans';
  font-size: 20px;
  font-style: normal;
  font-weight: 700;
  line-height: 28px;
  display: flex;
  align-items: center;
  gap: 10px;
}

.button-group {
  margin-right: 20px;
}

.layout-flow {
  background-color: #ffffff;
  height: 550px;
  width: 100%;
}

.drawer-title {
  color: #303133;
  font-family: 'MiSans';
  font-size: 18px;
  font-style: normal;
  font-weight: 700;
  line-height: 26px;
}

:deep(.el-drawer__header){
  margin-bottom: 0;
}

:deep(.el-drawer__body) {
  padding-top: 0;
}
</style>
